There is a Discount limitation type that can limit to "N times per customer", but it's not quite what you want.
If you are willing to defer the "warning" until shipping time, then you can try Shipping Director
You can see a similar example in this blog that will prevent shipping if more than 2 free items are in the cart. (If you prevent shipping, then customer can't finalize the order).
I can prevent the shipping where a customer try to get 2 or more free items. But I cannot prevent the customer to re-order the same free sample over and over through different order.
Yes, the blog was just an example. Checking prior orders is a little different. Need to get Customer's Orders, the blog had an example for that
Placed 2 or more orders in past 30 days Customer.Orders.Where((DateTime.Now - CreatedOnUtc).TotalDays <= 30).Count() >= 2
But, Orders have OrderProductVariants rather than Items (in shopping cart):
Type ErrorExit Name Can't have free items if prior orders have free items Expression Items.Any(ProductVariant.Price = 0) and Customer.Orders.Any(OrderProductVariants.Any(UnitPriceExclTax = 0)) Description Expression "Sorry, I see you have a prior order with free items. Only one per customer"
This assumes you are just looking at price to determine ANY prior free items. If you want to allow your customer to sample different free items (but not the same one), then that would be a bit more complex.
I am also interested in similar functionality. I envision a "Sample" button for each product that would add a sample quantity of the product to the shopping cart. It would need to work for both real and virtual products.