For attaching:
This is pretty complicated, since you will have to deal with mispredictions. It is very possible that you pick up the ball on the client but the server disagrees, you will then need a clean way to rewind this without causing havoc. There is no easy way to do this, you will have to understand the involved systems on a fairly low level and come up with a creative solution that works for your game. If that sounds like too much, the best option would be to simply accept the lag in this case. You can mask the lag a little by creating local cosmetic effects (e.g. a sound effect and maybe some particles) whenever the client thinks they picked up the ball, although this could be confusing in cases where the pickup does not actually happen. A common pattern is to create one local effect when the prediction happens, and another local effect when the action was confirmed by the server. An example would be a predicted hit detection system that displays blood splatters on a predicted hit, but only plays a hit sound once the hit was confirmed by the server.
For throwing:
This is a much simpler case. If you don’t want this to lag you will have to disable the built-in replication (at least for throws that the player initiated) and build your own prediction system. This isn’t too complicated, you’ll just have to start the movement on the client and server separately, then frequently update the client position and fast-forward based on a timestamp sent by the server after each correction (otherwise the correction would “pull back” the ball).
Mispredictions will still happen, but you can reduce that by implementing your own simple ball physics that behave more deterministically, and you can also smooth out corrections by interpolating between the predicted and corrected positions.
One thing to consider however is that this means that your own throws will behave differently (predicted ahead of time, with occasional corrections) to balls thrown by other players (lagging behind reality, but smooth). One way to make this more consistent would be to also fast-forward throws of other players, but since you can’t predict when they will throw a ball, this means that the initial movement would be a huge sudden jump forward. Yet another possibility would be to use either method only for the beginning of a throw, and then slow down or speed up the local simulation as required until it matches the desired consistent behaviour.
As you already expected there is no simple one-size-fits-all solution, and because of that Unreal can’t provide you any ready made solution out of the box. Thankfully simulating and predicting a simple ball movement is probably the easiest case there is, but since this requires a custom solution it still requires quite a bit of thought and some expertise.