Thanks for the super clear demo.
Yes, there is a significant difference between how staggerTo() works on TweenMax and how it works on a Timeline (which probably isn't obvious to most users).
From the docs:
TweenMax
https://greensock.com/docs/TweenMax/static.staggerTo()
staggerTo() simply loops through the targets array and creates a to() tween for each object and then returns an array containing all of the resulting tweens (one for each object).
TimelineLite / Max
https://greensock.com/docs/TimelineMax/staggerTo()
staggerTo() simply loops through the targets array and creates a to() tween for each and then inserts it at the appropriate place on a new TimelineLite instance whose onComplete corresponds to the onCompleteAll (if you define one) and then appends that TimelineLite to the timeline (as a nested child).
So to further dig into your mystery its important to know what this is inside your function.
If you console.log(this) for the TweenMax you will get the last tween, which means this.target is the target of the last tween.
If you console.log(this) for the Timeline you will get a timeline (which is the new TimelineLite mentioned above). Timeline's don't have a target, which is why you are seeing undefined.
Hopefully this helps you better understand what is happening. Again, its not something most people will pick up on in the first few weeks or even months of using GSAP.
If you want to get the last target in a TimelineMax.staggerTo() you can use:
new TimelineMax().staggerTo(".square",1,{y:30},0.1,0,function(){
console.log("With TimelineMax");
console.log(this.getChildren()[this.getChildren().length-1].target);
});