Unreal Engine 4 uses a variable frame rate. While this is good for hardware scalability, it creates a challenge for the physics engine, which works best with small fixed time steps. Sub-stepping takes the total frame time and divides it into sub-steps. The physics simulation is then ticked multiple times per frame. The number of sub-steps taken will depend on how small your max sub-step delta time is set to. The smaller the max sub-step time the more stable your simulation will be, but at a greater CPU cost.
Sub-stepping is completely hidden from the user, which means that some calls to the physics engine have to be interpolated or maintained. For example, if a user applies a force to an Actor for a single frame, and the frame is internally sub-stepped N times, we need to apply the force for N consecutive simulation steps in order to achieve the same acceleration. Similarly, if the user sets the target location of an Actor, we must interpolate the target location over multiple sub-steps in order to maintain the desired speed. All of these details are already handled internally by UE4, but there are some CPU and memory costs associated with the required bookkeeping.
Another technical detail to be aware of is the way collision callbacks behave while sub-stepping. UE4 runs the physics sub-stepping in a separate physics thread, allowing the game thread to continue doing work. In order to get the best performance, we delay the collision callbacks until the final sub-step is done. This means that you can get several callbacks for the same collision. For example, if A collides with B and bounces off, you may get a callback for A and B overlapping AND a callback for A and B no longer overlapping in the same frame. Internally all callbacks are pushed into a queue and so callbacks from sub-step 1 will be processed before callbacks from sub-step 2.