An object is polymorphic when its specific type may vary.
The types a specific value may take, is called class.

It is trivial to copy an object if its type is known:

int x;
int y = x;
Here x is not polymorphic, so y is declared of same type (int) as x.
But if the specific type of x were unknown, then y could not be declared of any specific type.

The task: let a polymorphic object contain an instance of some specific type S derived from a type T.
The type T is known.
The type S is possibly unknown until run time.
The objective is to create an exact copy of such polymorphic object (not to create a reference, nor a pointer to).
Let further the type T have a method overridden by S.
This method is to be called on the copy to demonstrate that the specific type of the copy is indeed S.

T = { name=function(s) return "T" end, tostring=function(s) return "I am a "..s:name() end }
 
function clone(s) local t={} for k,v in pairs(s) do t[k]=v end return t end
S1 = clone(T)  S1.name=function(s) return "S1" end
 
function merge(s,t) for k,v in pairs(t) do s[k]=v end return s end
S2 = merge(clone(T), {name=function(s) return "S2" end})
 
function prototype(base,mixin) return merge(merge(clone(base),mixin),{prototype=base}) end
S3 = prototype(T, {name=function(s) return "S3" end})
 
print("T :  "..T:tostring())
print("S1:  " ..S1:tostring())
print("S2:  " ..S2:tostring())
print("S3:  " ..S3:tostring())
print("S3's parent:  "..S3.prototype:tostring())