Well best is mostly opinion based and not a good way to ask actually... anyway
What the other answer didn't mention:
Of course the smoothness doesn't come from Vector3.Lerp nor Coroutines but actually from the Time.deltaTime.
This Time.deltaTime value is the real time passed since the last frame. This allows to do all kind of smooth and especially always taking the same amount of real time movements and actions independent of the frame rate.
In terms of the specific usecase of movements I personally would prefer the usage of Vector3.MoveTowards over Vector3.Lerp because the later gets slower and slower as it gets closer to the target. (At least if you use the transform.position as first value as often done in examples)
Here is the example provided by the Unity scripting API
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform target;
public float speed;
void Update() {
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
}
Instead of target.position of course you can also just define a Vector3 as target position.
If you need collision detection than both shouldn't be used because you might just move the object to far in one step so the collision isn't triggered.
In this case you might find a hint in this post