Code written against one name can work with many different types, and the right version runs automatically. A loop calling shape.area() gets the circle's formula for circles and the square's for squares. The calling code never branches on type.
Languages support several flavours:
Subtype polymorphism: a subclass or implementation supplies its own version, and the object picks at runtime.
Ad-hoc polymorphism: one name, several parameter lists, resolved when the code is compiled. Operator overloading is the same idea.
Parametric polymorphism: generics, where one List<T> works for every element type.
Duck typing: in dynamic languages, any object with the right method fits, with no declared type.
The gain is that adding a type does not mean editing existing branches, so old code stays untouched. The cost is indirection. Reading a call site no longer tells you which method actually runs, and a debugger or a stack trace becomes the only honest answer.
Rewriting in plainer words…
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.