Thats just moving things around. At one point in your program, you'll have to pick which class to instantiate, probably from a Person factory of some kind, that will create a new Student, Teacher or Principal. This may be abstracted away with some magic in the ORM that is loading it from your database, it may be a factory you wrote yourself, but that "switch" will exist somewhere. Maybe you're going to use some kind of reflection to do it without a switch, maybe you'll have a lookup table of types, but somewhere that decision has to be made.
Now, if that decision is made somewhere, the same place could configure the behaviors by composition. So you could, at that point, simply have Persons, and have a constructor or setter method that take a move strategy as an argument and saved as a private member. Then the move method would simply invoke it.
This way, a Person can move in any way they need to, without any tight coupling. Here you only have "move", but there could be countless of things people can do, and putting them in distinct buckets falls apart once your system gets any kind of reasonable complexity.
That is when you see insane inheritance hierarchy that get refactored every other day because people forgot that transfer students and transfer teachers have things in common but someone made them inherit from student instead of a class between person and teacher/student.
Composition, mixin, strategies, and other loose coupling patterns that don't associate actions with "is a" relationships are so, so much more flexible for systems you have to maintain for a significant amount of time... Its kind of ironic that out of all languages, Javascript got it right, and did so by accident.